<?php

namespace LDL\Twspider;

/*use LDL\Twspider\C\Timeout;
use LDL\Twspider\C\TimeRun;*/
use LDL\Twspider\E\TwDefFactory;
use VDB\Spider\Stackable;

//define("LOG_LEVEL",6);
//
class Spider extends \Pool
    //extends \Volatile
{
    //public static  $_Q=0 ;
    private $_sp;
    /**
     * @var TwPool
     */
    //public $_pool;

    protected function twspider($url = null, $configFactory = null, $metaData = null)
    {
        return new Twspider($url, $configFactory);
    }
    public function currentWorkersNum(){
       // $this->dump();
        if($this->workers!==null){
            return count(array_keys($this->workers));
        }
        return 0;
    }
    public function __construct($url = null, $configFactory = null, $metaData = null)
    {
        //parent::__construct();
        global $LOGGER, $_Q;
        //
        //try {
        if ($configFactory == null) {
            $configFactory = new TwDefFactory(__DIR__ . "/../../../../../..");
        }

        $this->_sp = $this->twspider($url, $configFactory);

        //  debug($this->_sp);
        //debug($this->twspider($url, $configFactory));
//		、、var_dump($LOGGER);exit ;

        $this->logger = $LOGGER;

        $this->prepareCrawl();
        //var_dump($_Q);
        $_Q = $this->getQueueManager();
        //var_dump($_Q);
        // debug("xxx");
        //$this->_sp->getQueueManager();// bug ? in php7,must setFirst ,if set IN member ,the new Object will no refenence,will destroyed

        if (!empty($url)) {
            $_Q->addUri($this->getUri($url));
        }
        //	$_Q->addUri($this->_sp->getUri($url));
        //seed ?????????????? ?í??  ?ò?? SUBMIT???ê?????° WORKer??????

        //}
        //	debug($this->_sp->getQueueManager()->count()) ;
        //$this->metaData = Stackable::instance(array_merge(is_array($metaData) ? $metaData : array(), array("spider" => &$this)));
        $this->metaData = Stackable::instance(is_array($metaData) ? $metaData : array());
      //  $this->metaData['spider']=$this;
      //  $poolName = $this->poolClass();
        $worknum=$this->workNum();
        $this->workIdMax= $worknum -1 ;
        parent::__construct($worknum, $this->getWorkClassName(), [$this->_sp, $this]);
    }
    /*public function worker_list(){
        if ($this->workers !== null)
            return array_keys($this->workers);
        return null;
    }*/
    public function getWorkClassName()
    {
        return TwWorker::class;
    }

    public function __call($method, $arguments)
    {
        return call_user_func_array(array($this->_sp, $method), $arguments);
        //echo  $method."is not found \n";
    }

    public static function __callStatic($method, $arguments)
    {
        return call_user_func_array(array(Twspider::class, $method), $arguments);

        ///	echo "$method\n" ;
    }

    function __get($name)
    {

        return $this->_sp->{$name};
    }
    function __set($name, $value)
    {
        //因为此对像不是Stackable 如果是stackable初始化有问题 那么设置对像时放到_sp _sp是多线程可共享的 fucking
        $this->_sp->{$name}=$value;
    }

    /**
     * 这个像JAVA  要在主MAIN 去启用 不然 程序 就结束 了
     */
    public function join()
    {
        if (!$this->started) {
            throw new \LogicException("no started");
        }
      /* while(true){
            $this->collect(function($work){
                var_dump("working is ".get_class($work));
                sleep(10);
                return false;
            });
           var_dump("collect");

           var_dump( $this->aaaa); $this->dump();
           sleep(10);
        }*/

         $this->shutdown();
        //	var_dump("join...........................");
    }

    protected function taskNum()
    {
        return 2;
    }
    private function workNum(){
        return $this->taskNum()>=8 ? round( $this->taskNum()/4): 2 ;
    }

    public function start()
    {

      //  global $LOGGER;
        for ($i =0; $i <=$this->workIdMax; $i++) {
            $iid=parent::submit(new \Threaded());
            $this->logger->debug("初始化通道%d:" ,$iid);
        }
        $this->nachChan();

        $this->started = true;
    }
    protected function nachChan(){
        $tasknum = $this->taskNum();
        for ($i = $tasknum; $i > 0; $i--) {
            $workid=$this->addTask($this->getSpiderTask());
            $this->logger->debug("启动任务%02d ,所在通道%d:" ,($tasknum + 1 - $i),$workid);
        }
    }
    public $started = false;

    protected function getSpiderTask()
    {
        return new Task();
    }

    /**
     * 加入1-max 通道 ，0号不加入 做为特殊
     * @return int workId
     */
    public  function workidIfNull(){
        return rand(1,$this->workIdMax);
    }
    /**
     * @param C\SpThreaded $task
     * @param null $workId 不指定就打入不为0的通道
     * @return int
     */
   final public function addTask(C\SpThreaded $task,$workId=null)
   {
       if ($workId === null) {
           $workId = $this->workidIfNull();
       }
       $reid = null;
       try {
           $this->dump();
           $reid = $this->submitTo($workId, $task);
       } catch (\Exception $e) {
           $this->logger->error($e->getMessage());
           // parent::submit(new \Threaded());//此方法必须在shutdown之前调用  属于初始化方法
       }
       return $reid;
   }
    final public function forckTask(C\SpThreaded $task,$workId=null)
    {

    }
    public function dump(){
      var_dump("总任务:".count($this->work));
        var_dump("workers size:".count($this->size));
        var_dump("workers:".count($this->workers));
        var_dump(array_keys($this->workers));

        /*   var_dump("metadataa spider is empty:".get_class($this->metaData['spider']));
           var_dump("metadataa spider is empty:".get_class($this->metaData['spider']->metaData));

           var_dump("metadataa pool is empty:".get_class($this->metaData['pool']));*/

    }
}
